from abc import ABC, abstractmethod
from typing import List, Tuple, Optional
import math

class Solver(ABC):
    @abstractmethod
    def solve(self, x0: List[float], expr: str, epsilon: float = 1e-6, max_iter: int = 100, precision: int = 50) -> List[Tuple[Optional[float], Optional[float], Optional[int]]]:
        pass

    @staticmethod
    @abstractmethod
    def is_available() -> bool:
        pass

class OriginalSolver(Solver):
    def solve(self, x0: List[float], expr: str, epsilon: float = 1e-6, max_iter: int = 100, precision: int = 50) -> List[Tuple[Optional[float], Optional[float], Optional[int]]]:
        namespace = {'__builtins__': {}, 'x': None}
        namespace.update({name: getattr(math, name) for name in dir(math) if not name.startswith('_')})
        
        def f(x):
            namespace['x'] = x
            try:
                return eval(expr, namespace)
            except Exception as e:
                raise ValueError(f"表达式计算错误: {str(e)}")
        
        def derivative(x):
            dx = 1e-6
            return (f(x + dx) - f(x)) / dx
        
        results = []
        for initial in x0:
            x = float(initial)
            for i in range(max_iter):
                try:
                    fx = f(x)
                    if abs(fx) < epsilon:
                        results.append((x, fx, i))
                        break
                    dfx = derivative(x)
                    if abs(dfx) < epsilon:
                        results.append((None, None, None))
                        break
                    x_new = x - fx / dfx
                    if abs(x_new - x) < epsilon:
                        results.append((x_new, f(x_new), i + 1))
                        break
                    x = x_new
                except Exception:
                    results.append((None, None, None))
                    break
            else:
                results.append((None, None, None))
        return results
    
    @staticmethod
    def is_available() -> bool:
        return True

class SympySolver(Solver):
    def __init__(self):
        import sympy as sp
        self.sp = sp
    
    def solve(self, x0: List[float], expr: str, epsilon: float = 1e-6, max_iter: int = 100, precision: int = 50) -> List[Tuple[Optional[float], Optional[float], Optional[int]]]:
        try:
            x_sym = self.sp.symbols('x')
            math_to_sympy = {
                'sin': self.sp.sin, 'cos': self.sp.cos, 'tan': self.sp.tan,
                'sqrt': self.sp.sqrt, 'log': self.sp.log, 'exp': self.sp.exp,
                'pi': self.sp.pi, 'e': self.sp.E
            }
            f = self.sp.sympify(expr, locals=math_to_sympy)
            df = self.sp.diff(f, x_sym)
            f_lambda = self.sp.lambdify(x_sym, f, ['math'])
            df_lambda = self.sp.lambdify(x_sym, df, ['math'])
        except Exception as e:
            raise ValueError(f"表达式解析错误: {str(e)}")
        
        results = []
        for initial in x0:
            xn = self.sp.Float(initial, precision)  # 使用高精度浮点数
            tol = self.sp.Float(epsilon, precision)
            for i in range(max_iter):
                try:
                    fx = float(f_lambda(xn))  # 转换为普通浮点数以避免精度问题
                    if abs(fx) < epsilon:
                        results.append((float(xn), fx, i))
                        break
                    dfx = float(df_lambda(xn))
                    if abs(dfx) < epsilon:
                        results.append((None, None, None))
                        break
                    xn = xn - fx / dfx  # 高精度计算
                except Exception:
                    results.append((None, None, None))
                    break
            else:
                results.append((None, None, None))
        return results
    
    @staticmethod
    def is_available() -> bool:
        try:
            import sympy
            return True
        except ImportError:
            return False